package com.dms.modules.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dms.modules.user.dto.*;
import com.dms.modules.user.entity.User;
import com.dms.modules.user.entity.UserAddress;
import com.dms.modules.user.entity.UserFavorite;
import com.dms.modules.user.mapper.UserAddressMapper;
import com.dms.modules.user.mapper.UserMapper;
import com.dms.modules.user.service.UserAddressService;
import com.dms.modules.user.service.UserFavoriteService;
import com.dms.modules.user.service.UserCenterService;
import com.dms.modules.user.vo.UserInfoVO;
import com.dms.modules.merchant.dto.MerchantApplyDTO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import com.dms.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class UserCenterServiceImpl extends ServiceImpl<UserMapper, User> implements UserCenterService {

    private final UserAddressService userAddressService;
    private final UserFavoriteService userFavoriteService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    private final RedisTemplate<String, String> redisTemplate;
    @Autowired
    private UserAddressMapper userAddressMapper;
    @Autowired
    private com.dms.common.utils.DmsSmsService smsSender;

    public UserCenterServiceImpl(
            UserAddressService userAddressService,
            UserFavoriteService userFavoriteService,
            RedisTemplate<String, String> redisTemplate) {
        this.userAddressService = userAddressService;
        this.userFavoriteService = userFavoriteService;
        this.redisTemplate = redisTemplate;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long register(UserRegisterDTO registerDTO) {
        // 检查用户名是否已存在
        if (lambdaQuery().eq(User::getUsername, registerDTO.getUsername()).count() > 0) {
            throw new BusinessException("用户名已存在");
        }
        
        // 检查手机号是否已注册
        if (getByPhone(registerDTO.getPhone()) != null) {
            throw new BusinessException("该手机号已被注册，请使用其他手机号或找回密码");
        }
        
        // 检查邮箱是否已注册
        if (registerDTO.getEmail() != null && getByEmail(registerDTO.getEmail()) != null) {
            throw new BusinessException("该邮箱已被注册，请使用其他邮箱或找回密码");
        }
        
        // 创建用户
        User user = new User();
        BeanUtils.copyProperties(registerDTO, user);
        user.setPassword(passwordEncoder.encode(registerDTO.getPassword()));
        user.setDeleted(0);
        
        save(user);
        return user.getId();
    }

    @Override
    public UserInfoVO getUserInfo(Long userId) {
        User user = getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        UserInfoVO userInfoVO = new UserInfoVO();
        BeanUtils.copyProperties(user, userInfoVO);
        return userInfoVO;
    }

    @Override
    public void updateUserInfo(Long userId, UserUpdateDTO updateDTO) {
        User user = getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        BeanUtils.copyProperties(updateDTO, user);
        updateById(user);
    }

    @Override
    public List<UserAddress> getAddressList(Long userId) {
        return userAddressService.lambdaQuery()
                .eq(UserAddress::getUserId, userId)
                .orderByDesc(UserAddress::getIsDefault)
                .orderByDesc(UserAddress::getCreateTime)
                .list();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addAddress(Long userId, AddressDTO addressDTO) {
        // 如果设置为默认地址，先将其他地址设为非默认
        if (addressDTO.getIsDefault() == 1) {
            userAddressMapper.updateDefaultStatus(userId, false);
        }

        UserAddress address = new UserAddress();
        BeanUtils.copyProperties(addressDTO, address);
        address.setUserId(userId);
        userAddressMapper.insert(address);
        return address.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAddress(Long userId, Long addressId, AddressDTO addressDTO) {
        UserAddress address = userAddressMapper.selectById(addressId);
        if (address == null || !address.getUserId().equals(userId)) {
            throw new BusinessException("地址不存在");
        }

        // 如果设置为默认地址，先将其他地址设为非默认
        if (addressDTO.getIsDefault() == 1 && address.getIsDefault() != 1) {
            userAddressMapper.updateDefaultStatus(userId, false);
        }

        BeanUtils.copyProperties(addressDTO, address);
        return userAddressMapper.updateById(address) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteAddress(Long userId, Long addressId) {
        UserAddress address = userAddressMapper.selectById(addressId);
        if (address == null || !address.getUserId().equals(userId)) {
            throw new BusinessException("地址不存在");
        }

        return userAddressMapper.deleteById(addressId) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean setDefaultAddress(Long userId, Long addressId) {
        UserAddress address = userAddressMapper.selectById(addressId);
        if (address == null || !address.getUserId().equals(userId)) {
            throw new BusinessException("地址不存在");
        }

        // 先将所有地址设为非默认
        userAddressMapper.updateDefaultStatus(userId, false);
        
        // 设置当前地址为默认
        address.setIsDefault(1);
        return userAddressMapper.updateById(address) > 0;
    }

    @Override
    public UserAddress getDefaultAddress(Long userId) {
        return userAddressService.lambdaQuery()
                .eq(UserAddress::getUserId, userId)
                .eq(UserAddress::getIsDefault, 1)
                .one();
    }

    @Override
    public IPage<UserFavorite> getFavoriteList(Long userId, Integer type, Integer pageNum, Integer pageSize) {
        Page<UserFavorite> page = new Page<>(pageNum, pageSize);
        return userFavoriteService.lambdaQuery()
                .eq(UserFavorite::getUserId, userId)
                .eq(UserFavorite::getType, type)
                .orderByDesc(UserFavorite::getCreateTime)
                .page(page);
    }

    @Override
    public boolean addFavorite(Long userId, FavoriteDTO favoriteDTO) {
        return userFavoriteService.addFavorite(favoriteDTO.getType(), favoriteDTO.getTargetId());
    }

    @Override
    public boolean cancelFavorite(Long userId, Long favoriteId) {
        UserFavorite favorite = userFavoriteService.getById(favoriteId);
        if (favorite == null || !favorite.getUserId().equals(userId)) {
            return false;
        }
        return userFavoriteService.removeById(favoriteId);
    }

    @Override
    public void sendVerifyCode(String phone, Integer type) {
        // 检查发送频率，同一手机号1分钟内不能重复发送
        String sendTimeKey = "verify:sendTime:" + phone;
        String lastSendTime = redisTemplate.opsForValue().get(sendTimeKey);
        if (lastSendTime != null) {
            long lastTime = Long.parseLong(lastSendTime);
            if (System.currentTimeMillis() - lastTime < 60000) {
                throw new BusinessException("发送验证码过于频繁，请稍后再试");
            }
        }

        // 生成6位随机验证码
        String verifyCode = String.format("%06d", new Random().nextInt(1000000));
        
        try {
            // 保存验证码到Redis，有效期5分钟
            String verifyKey = "verify:code:" + phone + ":" + type;
            redisTemplate.opsForValue().set(verifyKey, verifyCode, 5, TimeUnit.MINUTES);
            
            // 记录发送时间
            redisTemplate.opsForValue().set(sendTimeKey, String.valueOf(System.currentTimeMillis()), 1, TimeUnit.MINUTES);
            
            // 开发环境下，直接在日志中打印验证码
            log.info("模拟发送验证码成功，手机号: {}, 验证码: {}", phone, verifyCode);
            
        } catch (Exception e) {
            log.error("保存验证码失败: {}", e.getMessage(), e);
            throw new BusinessException("发送验证码失败，请稍后重试");
        }
    }

    private User getByPhone(String phone) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getPhone, phone);
        return getOne(wrapper);
    }

    private User getByEmail(String email) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getEmail, email);
        return getOne(wrapper);
    }

    @Override
    public User getProfile(Long userId) {
        return getById(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUserProfile(Long userId, UserProfileDTO profileDTO) {
        User user = getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 只更新允许修改的字段
        user.setNickname(profileDTO.getNickname());
        user.setGender(profileDTO.getGender());
        user.setPhone(profileDTO.getPhone());
        user.setEmail(profileDTO.getEmail());
        user.setBirthday(profileDTO.getBirthday());
        user.setSignature(profileDTO.getSignature());
        user.setUpdateTime(new Date());

        return updateById(user);
    }

    @Override
    public boolean updateProfile(Long userId, UpdateProfileDTO updateProfileDTO) {
        UserProfileDTO profileDTO = new UserProfileDTO();
        BeanUtils.copyProperties(updateProfileDTO, profileDTO);
        return updateUserProfile(userId, profileDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePassword(Long userId, UpdatePasswordDTO updatePasswordDTO) {
        User user = getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        if (!passwordEncoder.matches(updatePasswordDTO.getOldPassword(), user.getPassword())) {
            throw new BusinessException("原密码错误");
        }

        user.setPassword(passwordEncoder.encode(updatePasswordDTO.getNewPassword()));
        return updateById(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAvatar(Long userId, String avatarUrl) {
        User user = getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        user.setAvatar(avatarUrl);
        return updateById(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePhone(Long userId, String phone) {
        // 检查手机号是否已被其他用户使用
        if (getOne(new LambdaQueryWrapper<User>()
                .eq(User::getPhone, phone)
                .ne(User::getId, userId)) != null) {
            throw new BusinessException("该手机号已被其他用户使用");
        }

        User user = getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        user.setPhone(phone);
        return updateById(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateEmail(Long userId, String email) {
        // 检查邮箱是否已被其他用户使用
        if (getOne(new LambdaQueryWrapper<User>()
                .eq(User::getEmail, email)
                .ne(User::getId, userId)) != null) {
            throw new BusinessException("该邮箱已被其他用户使用");
        }

        User user = getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        user.setEmail(email);
        return updateById(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handleMerchantApply(Long userId, MerchantApplyDTO applyDTO) {
        // TODO: 实现商家申请逻辑
        throw new BusinessException("功能暂未实现");
    }

    @Override
    public void changePassword(Long userId, String oldPassword, String newPassword) {
        User user = getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
            throw new BusinessException("原密码错误");
        }
        
        user.setPassword(passwordEncoder.encode(newPassword));
        updateById(user);
    }

    @Override
    public void resetPassword(String phone, String newPassword) {
        User user = getByPhone(phone);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        user.setPassword(passwordEncoder.encode(newPassword));
        updateById(user);
    }
} 